'''
Created on 31.05.2011

This code based on GCHProject from projport project 
(http://code.google.com/p/projport/)

@author: 
@author: blaze
@license: New BSD License 

'''
# Data imported for Google Code Hosting.
# Use GData API 2.0.14
import datetime

from t2g.utils.logger import logger
from t2g.utils.markup import trac2gch

# TODO: 
#
#  - Add markup conventer (http://code.google.com/p/support/wiki/WikiSyntax#Wiki_Syntax)
#    #456 -> issue 456
#    [456] -> revision 456
class GCHWriter():
  
    """A Google Code Hosting Project, reachable through a client."""
    def __init__(self, projname, client, username, defaulIssueOwner):
        self.projname = projname
        self.client = client
        self.username = username
        self.defaulIssueOwner = defaulIssueOwner
        self.usermap = {}
        
    def setUserMap(self, usermap):
        self.usermap = usermap

    def issue_id_from_atom_id(self, atom_id):
        """Convert an atom.data.Id representing an issue ID to the ID string."""
        # TODO: Issue #131
        # "http://code.google.com/feeds/issues/p/projport/issues/full/27"
        # is the text part of the atom_id; we want the number on the end.
        return atom_id.text[atom_id.text.rfind('/') + 1:]

    def _translate_issue_ids(self, desc_or_comment):
        """Append to DESC_OR_COMMENT a note showing the mapping between
        issue ids from the original tracker mentioned in DESC_OR_COMMENT
        and issue ids in the new tracker.  This is to enable users to
        still follow links between issues even after switching trackers, e.g.:

        ### NOTE: The old issue ids mentioned in this comment map to
        ### new issue ids in the following way:
        ###
        ###    MAP-61   ==>  issue #70
        ###    MAP-123  ==>  issue #152
        ###    MAP-125  ==>  issue #154

        See self.issues_translation_table."""
        # TODO: Issue #132
        pass

    def _map_user(self, owner):        
        mappedOwner = owner
        originalOwner = owner.lower()
        
        if self.usermap.has_key(originalOwner):
            mappedOwner = self.usermap.get(originalOwner)
        else:
            mappedOwner = self.defaulIssueOwner
            
        logger.debug("Map user owner from %s to %s"  % (owner, mappedOwner))
        return mappedOwner
    
    def import_issue(self, issue):
        """Import ISSUE into this Google Code Hosting project.
        Return the Google Code Hosting issue thus created."""
        #owner = self.usermap.get_user(issue.assignee.source_username)
    
        logger.info("Import issue %s to GCH" % issue)
        
        owner = self._map_user(issue.reporter)
        
        #Convert description markup    
        dest_desc = trac2gch(issue.description)
        #If issue don't have description use summary instead
        if len(dest_desc) < 1:
            dest_desc = issue.summary
            
        #Save information about original author of issue:
        dest_desc = "(%s:%i) Originaly reported by %s on %s\n\n%s" % ("Trac", issue.id, issue.reporter, datetime.datetime.fromtimestamp(issue.time),  dest_desc)
        
        dest_status = "New"  # default to something the devs will see
        dest_label = []
    
        # Determine the destination's status/resolution.
        #
        # TRAC statuses:    New, Assigned, Closed, Reopened,
        # TRAC resolutions: fixed, worksforme, wantfix, invalid
        # 
        # (In TRAC, 'New', 'Assigned' or 'Reopened' status always means 'Unresolved'
        # resolution, and status 'Closed' means some other resolution.)
        #
        # Google statuses: New, Accepted, Started, [Closed status, see below]
        #                  Fixed, Verified, Invalid, Duplicate, WontFix, Done
        #
        # So we need to fold TRAC's status/resolution combinations into
        # Google's single status code.  Note that some of the Google
        # statuses have no TRAC analog, so we'll never generate them
        # in this converter.

        #Translate Trac issue status and resolution to GCH status
        if str(issue.status) == "closed":
            if str(issue.resolution) in ("fixed"):
                dest_status = "Fixed"
            elif str(issue.resolution) == "duplicate":
                dest_status = "Duplicate"
            elif str(issue.resolution) in ("invlid", "worksforme"):
                dest_status = "Invalid"
            elif str(issue.resolution) == "wontfix":
                dest_status = "WontFix"
        if str(issue.status) == "assigned":
            dest_status = "Accepted"

        # Translate TRAC priority to Google priority.
        if issue.priority:
            # TRAC has five priorities: Trivial, Minor, Major, Critical, Blocker
            # Google has four priorities: Critical, High, Medium, Low
            # Translate from the former to the latter as best we can.
            if (str(issue.priority) == "blocker" or
                str(issue.priority) == "critical"):
                dest_label.append("Priority-Critical")
            elif str(issue.priority) == "major":
                dest_label.append("Priority-High")
            elif str(issue.priority) == "minor":
                dest_label.append("Priority-Medium")
            elif str(issue.priority) == "trivial":
                dest_label.append("Priority-Low")
            else:
                dest_label.append("Priority-Medium")

        #Translate TRAC issue type to Google type
        if issue.type:
            # Trac has four types: defect, enhancement, task
            # Google has five types: Defect, Task, Enhancement, Review, Other
            # Translate from the former to the latter as best we can.
            if str(issue.type) == "defect":
                dest_label.append("Type-Defect")
            elif str(issue.type) == "task":
                dest_label.append("Type-Task")
            elif str(issue.type) == "enhancement":              
                dest_label.append("Type-Enhancement")
        else:
            dest_label.append("Type-Other")

        # Translate TRAC milestone to Google milestone.
        if issue.milestone:
            dest_label.append("Milestone-%s" % issue.milestone)
      
        # Translate TRAC version to (our made-up) Google version.
        if issue.version:
            dest_label.append("FoundIn-%s" % issue.version)
                
        gch_issue = self.client.add_issue(
            # project projname, not issue name
            self.projname,
            # We prepend the original issue's id to that title for
            # historical traceability.  Even better would be to actually
            # convert the links between issues to point to the new ones,
            # and it's perfectly possible to do so, but it's a lot easier
            # just to stick the original id in the title and let humans do
            # the searching on the rare occasions when they need to trace
            # back and forth between issues.
            #
            # Note that Google uses "title" for what we call "summary".
            "(%s:%i) %s" % ("Trac", issue.id, issue.summary),
            # And Google uses "summary" for what we call "description".
            dest_desc,
            # In the source code to add_issue, this parameter is named
            # "author", but as it happens, we want to pass owner for it
            # anyway (in online documentation, it is somewhat misleadingly
            # called "owner" too).
            owner,
            # Now the real owner field.  Unfortunately, passing it here
            # has no effect, and we have to do an additional call to
            # update_issue() afterwards to actually set the owner.
            owner=owner,
            status=dest_status, labels=dest_label)
        gch_issue_id_str = self.issue_id_from_atom_id(gch_issue.id)

        # Send comments.
        # Sort comments by date
        comments = issue.comments.getComments()
        comments.sort()
        
        for comment in comments:
            #comment_owner = self.usermap.get_user(c.author_username)
            comment_owner = self._map_user(comment.author)
            comment_date = datetime.datetime.fromtimestamp(comment.time)
            dest_comment = "Commented by %s on %s:\n\n%s" % (comment_owner, comment_date, comment.text)
            # TODO: Issue #137
            # TODO: Add backpointer to original comment
            #if self.source_type == "jira":
            #c_link = c.source_id
            
            #if self.issue_comment_link_template and issue.source_link:
            #    c_link = self.issue_comment_link_template \
            #    % (issue.source_link, c.source_id, c.source_id)
            #    dest_comment = issue.add_backpointer(
            #      c.body, "comment", c_link, c.author_username, c.date_created)
            
            self.client.update_issue(
                self.projname, gch_issue_id_str, self.username, owner=comment_owner, comment=dest_comment)
        
        return gch_issue